#include "getweather.hpp"

GetWeather::GetWeather(QObject *parent)
    : QObject(parent), manager(new QNetworkAccessManager(this))
{
    connect(manager, &QNetworkAccessManager::finished, this, &GetWeather::onFinished);
}

GetWeather::~GetWeather()
{
    // 由于使用了 parent-child 机制，这里不需要手动删除 manager
}

// 获取天气数据
void GetWeather::fetchWeatherByCity(const QString &apiKey, const QString &city)
{
    if (!validateApiKey(apiKey))
    {
        emit errorOccurred("无效的API密钥");
        return;
    }

    if (!validateCity(city))
    {
        emit errorOccurred("无效的城市名");
        return;
    }

    QUrl url("http://api.seniverse.com/v3/weather/now.json");
    QUrlQuery query;
    query.addQueryItem("key", apiKey);
    query.addQueryItem("location", city);
    query.addQueryItem("language", "zh-Hans");
    query.addQueryItem("unit", "c");

    url.setQuery(query);
    fetchWeatherData(url.toString());
}

// 发送请求
void GetWeather::fetchWeatherData(const QString &url)
{
    QUrl requestUrl(url);
    QNetworkRequest request(requestUrl);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    QNetworkReply *reply = manager->get(request);

    // 添加超时处理
    QTimer::singleShot(10000, reply, [reply, this]()
                       {
        if (reply->isRunning()) {
            reply->abort();
            emit errorOccurred("请求超时");
        } });
}

// 处理完成
void GetWeather::onFinished(QNetworkReply *reply)
{
    reply->deleteLater();

    if (reply->error())
    {
        emit errorOccurred(QString("网络错误: %1").arg(reply->errorString()));
        return;
    }

    QByteArray data = reply->readAll();

    // 保持原有的数据发送
    emit weatherDataFetched(QString(data));

    // JSON 解析错误检查
    QJsonParseError jsonError;
    QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
    if (jsonError.error != QJsonParseError::NoError)
    {
        emit errorOccurred(QString("JSON解析错误: %1").arg(jsonError.errorString()));
        return;
    }

    try
    {
        // 解析并发送结构化数据
        WeatherInfo info = parseWeatherData(data);
        emit weatherInfoReceived(info);
    }
    catch (const std::exception &e)
    {
        emit errorOccurred(QString("数据解析错误: %1").arg(e.what()));
    }
}

// 解析天气数据
WeatherInfo GetWeather::parseWeatherData(const QByteArray &data)
{
    WeatherInfo info;
    QJsonDocument doc = QJsonDocument::fromJson(data);

    if (doc.isNull() || !doc.isObject())
    {
        throw std::runtime_error("无效的JSON数据");
    }

    QJsonObject root = doc.object();

    // 错误处理
    if (root.contains("status_code") && root.contains("status"))
    {
        QString errorMsg = QString("API错误: %1 - %2")
                               .arg(root["status_code"].toString())
                               .arg(root["status"].toString());
        throw std::runtime_error(errorMsg.toStdString());
    }

    // 确保results数组存在且不为空
    if (!root.contains("results") || !root["results"].isArray() || root["results"].toArray().isEmpty())
    {
        throw std::runtime_error("找不到天气数据");
    }

    QJsonObject result = root["results"].toArray().first().toObject();
    QJsonObject now = result["now"].toObject();
    QJsonObject location = result["location"].toObject();

    // 提取位置信息（可选）
    QString locationName = location["name"].toString();

    // 提取天气数据
    info.temperature = now["temperature"].toString();
    info.condition = now["text"].toString();
    info.humidity = now["humidity"].toString();
    info.windDirection = now["wind_direction"].toString();
    info.windSpeed = now["wind_scale"].toString(); // 注意：API返回的是 wind_scale 而不是 wind_speed
    info.updateTime = result["last_update"].toString();

    // 调试输出
    //    qDebug() << "位置:" << locationName;
    //    qDebug() << "温度:" << info.temperature;
    //    qDebug() << "天气:" << info.condition;
    //    qDebug() << "湿度:" << info.humidity;
    //    qDebug() << "风向:" << info.windDirection;
    //    qDebug() << "风力:" << info.windSpeed;
    //    qDebug() << "更新时间:" << info.updateTime;

    return info;
}

// 验证API密钥
bool GetWeather::validateApiKey(const QString &apiKey)
{
    return !apiKey.isEmpty() && apiKey.length() >= 16; // 假设API密钥至少16个字符
}

// 验证城市名
bool GetWeather::validateCity(const QString &city)
{
    return !city.isEmpty() && city.length() <= 50; // 城市名不应过长
}

// 更新最近一次的天气信息
void GetWeather::updateLastWeatherInfo(const WeatherInfo &info)
{
    lastWeatherInfo = info;
}

// 获取格式化的天气信息
QString GetWeather::getFormattedWeatherInfo() const
{
    return QString("温度: %1°C\n"
                   "天气: %2\n"
                   "湿度: %3%\n"
                   "风向: %4\n"
                   "风力: %5\n"
                   "更新时间: %6")
        .arg(lastWeatherInfo.temperature)
        .arg(lastWeatherInfo.condition)
        .arg(lastWeatherInfo.humidity)
        .arg(lastWeatherInfo.windDirection)
        .arg(lastWeatherInfo.windSpeed)
        .arg(lastWeatherInfo.updateTime);
}

// 发送请求获取天气数据
std::string getWeatherString(const std::string &city)
{
    // 创建命令行参数
    int argc = 1;
    char *argv[] = {(char *)"dummy"};

    QCoreApplication app(argc, argv);
    GetWeather weather;
    WeatherResult result{false, ""};
    bool finished = false;

    // 连接天气信息接收信号
    QObject::connect(&weather, &GetWeather::weatherInfoReceived,
                     [&result, &finished](const WeatherInfo &info)
                     {
                         result.success = true;
                         result.message = QString("温度: %1°C\n"
                                                  "天气: %2\n"
                                                  "湿度: %3%\n"
                                                  "风向: %4\n"
                                                  "风速: %5\n"
                                                  "更新时间: %6")
                                              .arg(info.temperature)
                                              .arg(info.condition)
                                              .arg(info.humidity)
                                              .arg(info.windDirection)
                                              .arg(info.windSpeed)
                                              .arg(info.updateTime)
                                              .toStdString();
                         finished = true;
                     });

    // 连接错误信号
    QObject::connect(&weather, &GetWeather::errorOccurred,
                     [&result, &finished](const QString &error)
                     {
                         result.success = false;
                         result.message = error.toStdString();
                         finished = true;
                     });

    // 发起天气查询请求
    weather.fetchWeatherByCity(API_KEY, QString::fromStdString(city));

    // 等待操作完成
    while (!finished)
    {
        app.processEvents();
    }

    return result.message;
}

// 提取温度和天气
void extractWeatherAndTemperature(const std::string &weatherInfo, std::string &outTemp, std::string &outWeather)
{
    std::istringstream iss(weatherInfo);
    std::string line;
    std::getline(iss, line); // 获取第一行

    // 解析温度
    size_t posTemp = line.find("温度: ");
    if (posTemp != std::string::npos)
    {
        outTemp = line.substr(posTemp + 7);                   //  "温度: "
        outTemp.erase(outTemp.find("°C"), std::string::npos); // 移除 "°C"
        outTemp = "Temp: " + outTemp;
    }
    std::getline(iss, line);
    // 解析天气
    size_t posWeather = line.find("天气: ");
    if (posWeather != std::string::npos)
    {
        outWeather = line.substr(posWeather + 8); // "天气: "
        // 将中文转换为英文
        outWeather = "Weather: " + translateChineseWeather(outWeather);
        // outWeather.erase(outWeather.find_last_of("\n"), std::string::npos); // 移除换行符
    }
}

// 将中文天气转换为英文
std::string translateChineseWeather(const std::string &chineseWeather)
{
    // 天气翻译表
    static const std::map<std::string, std::string> weatherTranslations =
        {
            {"晴", "Sunny"},
            {"少云", "PartlyCloudy"},
            {"多云", "Cloudy"},
            {"阴", "Cloudy"},
            {"晴间多云", "SunnyCloudy"},
            {"大部多云", "MostlyCloudy"},
            {"雨", "Rainy"},
            {"小雨", "LightRain"},
            {"中雨", "ModerateRain"},
            {"大雨", "HeavyRain"},
            {"暴雨", "Storm"},
            {"大暴雨", "HeavyStorm"},
            {"特大暴雨", "SevereStorm"},
            {"阵雨", "Shower"},
            {"强阵雨", "HeavyShower"},
            {"雷阵雨", "Thunderstorm"},
            {"雷阵雨伴有冰雹", "Hail"},
            {"雪", "Snow"},
            {"小雪", "LightSnow"},
            {"中雪", "ModerateSnow"},
            {"大雪", "HeavySnow"},
            {"暴雪", "Blizzard"},
            {"风", "Wind"},
            {"微风", "LightWind"},
            {"强风", "StrongWind"},
            {"暴风", "StrongWind"},
            {"飓风", "Tornado"},
            {"龙卷风", "Gale"},
            {"雾", "Fog"},
            {"轻雾", "LightFog"},
            {"大雾", "HeavyFog"},
            {"霾", "Haze"},
            {"轻度霾", "LightHaze"},
            {"中度霾", "ModerateHaze"},
            {"重度霾", "HeavyHaze"},
            {"扬沙", "Sand"},
            {"沙尘暴", "DustStorm"},
            {"强沙尘暴", "HeavyDustStorm"},

        };

    auto it = weatherTranslations.find(chineseWeather);
    if (it != weatherTranslations.end())
    {
        // 如果在映射中找到了中文天气，返回对应的英文翻译
        return it->second;
    }
    else
    {
        // 如果没有找到，返回原字符串或处理错误
        return "Unknown";
    }
    return weatherTranslations.at(chineseWeather); // 返回翻译后的英文天气
}

// 初始化控制台编码的函数
void initConsole()
{
#ifdef _WIN32
    // Windows 系统下设置控制台代码页为 UTF-8
    SetConsoleOutputCP(CP_UTF8);
    // 如果还需要输入中文，也设置输入代码页
    SetConsoleCP(CP_UTF8);
#else
    // Linux/Unix 系统下设置本地化
    std::locale::global(std::locale("en_US.UTF-8"));
#endif
    // 设置 cout 使用 UTF-8
    std::cout.imbue(std::locale());
}
